﻿using APP.BaseClass;
using APP.IO;
using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace APP.OpenCV
{

    public enum TemplateType
    {
        Number,
        Bombo,
        Earth,
        Empty,
    }

    public class ChipMatchItemMode2
    {
        public string ImagePath { get; set; }

        public TemplateType TemplateType { get; set; }
        public int Number { get; set; }
        public Mat Source { get; set; }

    }

    /// <summary>
    ///  利用 https://zhuanlan.zhihu.com/p/101374450
    /// </summary>
    public class ImageMatchModel
    {
        static double minMatchRate = 0.9;
        static int thresh_Min = 130;
        static int thresh_Max = 255;
        static int Contours_Min = 80;
        static int Contours_Max = 400;

        List<ChipMatchItemMode2> OriginData = new List<ChipMatchItemMode2>();

        public void InitSource(string folder)
        {
            var files = new DirectoryInfo(folder).GetFiles();
            foreach (var file in files)
            {
                ChipMatchItemMode2 itemModel = new ChipMatchItemMode2();
                var itemString = Path.GetFileNameWithoutExtension(file.Name);
                var typeString = itemString.Split('_')[0];
                itemModel.ImagePath = file.FullName;
                itemModel.Source = Cv2.ImRead(file.FullName);
                if (int.TryParse(typeString, out int number))
                {
                    itemModel.TemplateType = TemplateType.Number;
                    itemModel.Number = number;
                    OriginData.Add(itemModel);
                }
                else if (Enum.TryParse(typeString, out TemplateType type))
                {
                    itemModel.TemplateType = type;
                    OriginData.Add(itemModel);
                }


            }
        }

        /// <summary>
        /// 从模版里匹配数字
        /// </summary>
        /// <param name="waitImagePath"></param>
        /// <returns></returns>
        public ChipMatchItemMode2 MatchTemplate(string waitImagePath, out double meanH)
        {
            var waitSource = Cv2.ImRead(waitImagePath);
            var mean = waitSource.GetMean();
            meanH = mean.Val1;
            var numberTemplateList = OriginData.Where(x => x.TemplateType == TemplateType.Number).ToList();
            foreach (var item in numberTemplateList)
            {
                var rate = MatchTemplateItem(waitImagePath, item.Source);
                if (rate > 0)
                {

                }
                if (rate > minMatchRate)
                {
                    return item;
                }
            }


            if (mean.Val1 >= 80)
            {
                var bomboTemplateList = OriginData.Where(x => x.TemplateType == TemplateType.Bombo).ToList();
                foreach (var item in bomboTemplateList)
                {
                    var rate = MatchTemplateItem(waitImagePath, item.Source);
                    if (rate > 0)
                    {

                    }
                    if (rate > minMatchRate)
                    {
                        return item;
                    }
                }

                return null;
            }
            else
            {
                return new ChipMatchItemMode2
                {
                    TemplateType = TemplateType.Empty,
                    Number = 0,
                };
            }
            return null;
        }

        /// <summary>
        /// 匹配模版
        /// </summary>
        /// <param name="waitImagePath"></param>
        /// <param name="templateImage"></param>
        /// <returns></returns>
        public double MatchTemplateItem(string waitImagePath, Mat templateImage)
        {
            Mat waitImage = Cv2.ImRead(waitImagePath);
            if (waitImage.Empty() || templateImage.Empty())
            {
                Console.WriteLine("请确认图像文件名称是否正确");
                return -1;
            }
            Mat result = new Mat();
            Cv2.MatchTemplate(templateImage, waitImage, result, TemplateMatchModes.CCoeffNormed);//模板匹配
            double maxVal, minVal;
            Point minLoc, maxLoc;
            //寻找匹配结果中的最大值和最小值以及坐标位置
            Cv2.MinMaxLoc(result, out minVal, out maxVal, out minLoc, out maxLoc);
            //绘制最佳匹配区域
            //Cv2.Rectangle(waitImage, new Rect(maxLoc.X, maxLoc.Y, templateImage.Cols, templateImage.Rows), new Scalar(0, 0, 255), 2);
            return maxVal;
        }

        /// <summary>
        /// 第一步给待识别的元素创建最小末班图片存在文件夹，通过名称区分，到时候加载进来
        /// </summary>
        /// <param name="folder"></param>
        /// <param name="outPutFolder"></param>
        public void CreateTemplate(string folder, string outPutFolder)
        {
            var files = new DirectoryInfo(folder).GetFiles();
            foreach (var file in files)
            {
                CreateTemplateItem(file.FullName, outPutFolder);
            }
        }
        /// <summary>
        /// 创建模版的单个项目
        /// </summary>
        /// <param name="imagePath"></param>
        public void CreateTemplateItem(string imagePath, string outPutFolder)
        {
            Mat SourceImage = Cv2.ImRead(imagePath);
            Mat grayImage = new Mat();
            Mat Image = new Mat();
            Mat dstImage = new Mat();
            SourceImage.CopyTo(dstImage);
            Cv2.CvtColor(SourceImage, grayImage, ColorConversionCodes.BGR2GRAY);
            Cv2.Threshold(grayImage, Image, thresh_Min, thresh_Max, ThresholdTypes.BinaryInv);

            Cv2.FindContours(Image, out Point[][] contours, out HierarchyIndex[] hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxNone);
            if (contours.Length > 0)
            {
                for (int itemIndex = 0; itemIndex < contours.Length; itemIndex++)
                {
                    var item = contours[itemIndex];
                    var itemRect = Cv2.BoundingRect(item);
                    Mat resultImage = new Mat(SourceImage, itemRect);

                    //var folder = PathHelper.GetPath(FolderType.Temp, "ImageContour");
                    var fileName = Path.GetFileNameWithoutExtension(imagePath);
                    var fileExtension = Path.GetExtension(imagePath);
                    var savePath = Path.Combine(outPutFolder, fileName + itemIndex + fileExtension);
                    //Cv2.DrawContours(resultImage, contours, itemIndex, new Scalar(0, 0, 255), 2);
                    Cv2.ImWrite(savePath, resultImage);
                }
            }
        }

    }
}
